package models

import (
	"errors"
	"gorm.io/gorm"
	"log"
)

type Category struct {
	gorm.Model
	Name       string   `json:"name" binding:"required"`
	ParentID   uint     `json:"parent_id" binding:"required"`
	Icon       string   `json:"icon" binding:"required"`
	Background string   `json:"background"`
	db         *gorm.DB `json:"-"`
}

func (p *Category) Delete(categoryID int) error {
	//TODO hook判断是否存在没有删除的下级分类
	err := p.HasChild(categoryID)
	if err != nil {
		return err
	}
	result := p.db.Delete(&Category{}, categoryID)
	return result.Error
}
func (p *Category) HasChild(categoryID int) (err error) {
	category := &Category{}
	result := p.db.Where("parent_id = ?", categoryID).First(category)
	if result.Error != nil || result.Error == gorm.ErrRecordNotFound {
		return
	}
	return errors.New("有下级菜单")
}

//delete hook
func (p *Category) BeforeDelete(tx *gorm.DB) (err error) {
	log.Printf("befor deleted hook")
	//p.HasChild()
	/*if u.Role == "admin" {
		return errors.New("admin user not allowed to delete")
	}*/
	return
}
func (p *Category) FindByName(name string) (*Category, error) {
	return p.FindByNameWithDeleted(name, false)
}
func (p *Category) FindByNameWithDeleted(name string, withDeleted bool) (*Category, error) {
	category := Category{}
	query := p.db.Where("name = ?", name)
	if withDeleted {
		query = query.Where("deleted_at is not null or deleted_at is null")
	}
	result := query.First(&category)
	if result.Error != nil {
		return nil, result.Error
	}
	return &category, nil
}
func (p *Category) Update(c *Category) (*Category, error) {
	result := p.db.Model(&Category{}).Updates(map[string]interface{}{
		"name":       c.Name,
		"parent_id":  c.ParentID,
		"icon":       c.Icon,
		"background": c.Background,
	})
	if result.Error != nil {
		return nil, result.Error
	}
	return c, nil
}

func (p *Category) Create(c *Category) (*Category, error) {
	result := p.db.Create(c)
	if result.Error != nil {
		return nil, result.Error
	}
	return c, nil
}

func (Category) TableName() string {
	return "categories"
}
func (p *Category) FindByID(product_id uint) (model *Category, err error) {
	model = &Category{}
	model.ID = product_id
	result := p.db.First(model)
	err = result.Error
	return
}

func (p *Category) FindByCategoryID(page, rows int, parent_id uint) (pages *Pages, err error) {
	var data []Category
	var all int64
	pages = &Pages{}
	query := p.db.Model(Category{}).Where("parent_id = ?", parent_id)
	//all
	result := query.Count(&all)
	if result.Error != nil {
		return nil, result.Error
	}
	query.Limit(rows).Offset((page - 1) * rows).Find(&data)
	result = query.Count(&all)
	if result.Error != nil {
		return nil, result.Error
	}
	return NewPages(page, rows, all, data), nil
}

type ICategory interface {
	FindByID(category_id uint) (*Category, error)
	FindByCategoryID(page, rows int, parent_id uint) (pages *Pages, error error)
	Create(c *Category) (*Category, error)
	Update(c *Category) (*Category, error)
	FindByName(name string) (*Category, error)
	Delete(categoryID int) error
}

func NewCategory(db *gorm.DB) ICategory {
	return &Category{db: db}
}
